package sdb

import (
	"os"
	"fmt"
	"goaws.googlecode.com/hg/aws"
)

func (d *Domain) GetAttributes(item string, names []string, consistentRead bool) (attrs aws.AttributeList, err os.Error) {
	params := map[string]string{"ItemName": item}
	if names != nil {
		aws.AddAttributeNamesToParams(params, names)
	}
	if consistentRead {
		params["ConsistentRead"] = "true"
	}

	response := new(getAttributesResponse)
	if err = d.getResponse("GetAttributes", params, response); err != nil {
		return
	}

	return response.Attributes, nil
}

func (d *Domain) GetAllAttributes(item string, consistentRead bool) (attrs aws.AttributeList, err os.Error) {
	return d.GetAttributes(item, nil, consistentRead)
}

func (d *Domain) PutAttributes(item string, attrs aws.AttributeList, replace bool) (err os.Error) {
	params := make(map[string]string)
	params["ItemName"] = item
	for i, attr := range attrs {
		params[fmt.Sprintf("Attribute.%d.Name", i+1)] = attr.Name
		params[fmt.Sprintf("Attribute.%d.Value", i+1)] = attr.Value
		if replace {
			params[fmt.Sprintf("Attribute.%d.Replace", i+1)] = "true"
		}
	}

	return d.getResponse("PutAttributes", params, nil)
}

func (d *Domain) AddAttributes(item string, attrs aws.AttributeList) (err os.Error) {
	return d.PutAttributes(item, attrs, false)
}

func (d *Domain) ReplaceAttributes(item string, attrs aws.AttributeList) (err os.Error) {
	return d.PutAttributes(item, attrs, true)
}

func (d *Domain) ReplaceExistingValue(item, name, oldValue, newValue string) (err os.Error) {
	params := map[string]string{
		"ItemName":            item,
		"Attribute.1.Name":    name,
		"Attribute.1.Value":   newValue,
		"Attribute.1.Replace": "true",
		"Expected.1.Name":     name,
		"Expected.1.Value":    oldValue,
	}

	return d.getResponse("PutAttributes", params, nil)
}

func (d *Domain) AddNonExistingValue(item, name, value string) (err os.Error) {
	params := map[string]string{
		"ItemName":          item,
		"Attribute.1.Name":  name,
		"Attribute.1.Value": value,
		"Expected.1.Name":   name,
		"Expected.1.Exists": "false",
	}

	return d.getResponse("PutAttributes", params, nil)
}

func (d *Domain) BatchPutAttributes(items []Item, replace bool) (err os.Error) {
	params := make(map[string]string)
	for i, item := range items {
		params[fmt.Sprintf("Item.%d.ItemName", i+1)] = item.Name
		for j, attr := range item.Attributes {
			params[fmt.Sprintf("Item.%d.Attribute.%d.Name", i+1, j+1)] = attr.Name
			params[fmt.Sprintf("Item.%d.Attribute.%d.Value", i+1, j+1)] = attr.Value
			if replace {
				params[fmt.Sprintf("Item.%d.Attribute.%d.Replace", i+1, j+1)] = "true"
			}
		}
	}

	return d.getResponse("BatchPutAttributes", params, nil)
}

func (d *Domain) BatchAddAttributes(items []Item) (err os.Error) {
	return d.BatchPutAttributes(items, false)
}

func (d *Domain) BatchReplaceAttributes(items []Item) (err os.Error) {
	return d.BatchPutAttributes(items, true)
}

func (d *Domain) DeleteAttributes(item string, names []string, nameValues aws.MultiMap) (err os.Error) {
	params := map[string]string{"ItemName": item}
	i := 1
	for _, name := range names {
		params[fmt.Sprintf("Attribute.%d.Name", i)] = name
		i++
	}
	for name, values := range nameValues {
		for _, value := range values {
			params[fmt.Sprintf("Attribute.%d.Name", i)] = name
			params[fmt.Sprintf("Attribute.%d.Value", i)] = value
			i++
		}
	}

	return d.getResponse("DeleteAttributes", params, nil)
}

func (d *Domain) DeleteAllAttributes(item string) (err os.Error) {
	return d.DeleteAttributes(item, nil, nil)
}

func (d *Domain) DeleteExistingValue(item, name, oldValue string) (err os.Error) {
	params := map[string]string{
		"ItemName":         item,
		"Expected.1.Name":  name,
		"Expected.1.Value": oldValue,
	}

	return d.getResponse("DeleteAttributes", params, nil)
}
